//
//  ServiceProvider.h
//  Rich
//
//  Created by Kenny Chen on 12/12/17.
//  Copyright (c) 2012年 Kenny Chen. All rights reserved.
//

#ifndef Rich_RichCore_h
#define Rich_RichCore_h

#import <Foundation/Foundation.h>
#import "RichAppDelegate.h"
#import "SQLiteManager.h"
#import "RichError.h"

#define RichDelegate                 (RichAppDelegate *)[[UIApplication sharedApplication] delegate]
#define RichLocaleString(str)        NSLocalizedString(str, @"Rich")

#define DB_VER_MAJOR                 0
#define DB_VER_MINOR                 1
#define RichDatabaseVersion          ((DB_VER_MAJOR << 16) | DB_VER_MINOR)

#define RichDatabaseUserAuth         @"RichUserAuth.db"
#define RichDatabaseData             @"RichData.db"
#define RichDatabaseDataBackup       @"RichDataBackup.db"

#define RichTableAmount              8
#define RichtableVersion             @"version"
#define RichTableCurrency            @"currency"
#define RichTableAccounts            @"accounts"
#define RichTableCategory            @"categories"
#define RichTableCreditCardBill      @"credit_card_bill"
#define RichTableGeneralTransactions @"transaction_general"
#define RichTableStockTransactions   @"transaction_stock"
#define RichTableFundTransactions    @"transaction_fund"

#define kTransactionTypeGeneral      @"TransactionTypeGeneral"
#define kTransactionTypeStock        @"TransactionTypeStock"
#define kTransactionTypeFund         @"TransactionTypeFund"

#define RichCoreNotificationReloadAccount        @"ReloadAccountNotification"
#define RichCoreNotificationReloadCategory       @"ReloadCategoryNotification"
#define RichCoreNotificationReloadTransaction    @"ReloadTransactionNotification"
#define RichCoreNotificationReloadCreditCardBill @"ReloadCreditCardBillNotification"

#define ROWS_PER_PAGE     20

#pragma mark - Rich Account

typedef enum {
    AccountTypeNotSupport         = -1,
    AccountTypeCash               = 0,      // 現金帳戶
    AccountTypeDepositSavings     = 1,      // 活存帳戶
    AccountTypeDepositTimeDeposit = 2,      // 定存帳戶
    AccountTypeDepositChecking    = 3,      // 支票帳戶
    AccountTypeDepositMoneyMarket = 4,      // 貨幣市場帳戶 (類似支票帳戶, 利息較高)
    AccountTypeStoredValueCards   = 5,      // 儲值卡
    AccountTypeCreditCards        = 6,      // 信用卡帳戶
    AccountTypeInsurance          = 7,      // 保險帳戶
    AccountTypeVisibleEnd,
    AccountTypeInvestmentStocks   = 50,     // 股票帳戶 (包含權證)
    AccountTypeInvestmentFunds    = 51,     // 基金帳戶
    AccountTypeInvestmentFutures  = 52,     // 期貨帳戶
    AccountTypeInvestmentOptions  = 53,     // 選擇權帳戶
    AccountTypeInvisibleEnd,
    AccountTypeAll,
} AccountType;

typedef enum {
    AccountPropertyDefault = 0,
    AccountPropertyNoStatistic,
    AccountPropertyCreditCardAutoPay,
    AccountPropertyStockSettlement,
    AccountPropertyEnd
} AccountProperty;

@interface RichAccount : NSObject

@property (assign)            NSInteger       accountId;
@property (nonatomic, retain) NSString *      name;
@property (assign)            AccountType     type;
@property (nonatomic, retain) NSString *      currencyCode;
@property (assign)            double          initialBalance;
@property (assign)            double          balance;
@property (nonatomic, retain) NSDate *        balanceDate;
@property (assign)            double          creditCardAPR;
@property (assign)            AccountProperty property;
@property (nonatomic, retain) NSString *      description;

@end

#pragma mark - Rich Currency

@interface RichCurrency : NSObject

@property (nonatomic, retain) NSString * code;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * symbol;
@property (assign)            NSUInteger position;
@property (nonatomic, retain) NSString * format;

@end

#pragma mark - Rich Default Category

typedef enum {
    RootCategoryUnknown = 0,
    RootCategoryExpend,
    RootCategoryIncome,
    RootCategoryTransfer,
    RootCategoryAll = 0xff
} RootCategory;

typedef NSUInteger RichCategoryCode;

#define RichCategoryCodeRoot    0

#pragma mark - Rich General Transaction

// TODO: [Transaction] property? event?
typedef enum {
    /* Expend properties */
    TransactionPropertyExpendNone = 0,
    TransactionPropertyExpendNeed,
    TransactionPropertyExpendWant,

    /* Income properties */
    TransactionPropertyIncomeNone = 100,
    TransactionPropertyIncomeLabor,
    TransactionPropertyIncomeInterest,

    /* Transfer properties */
    TransactionPropertyTransferNone = 200,

    /* Internal use properties */
    TransactionPropertyInternalCreditCardPayment = (1 << 16),   // 自動轉帳付款
    TransactionPropertyInternalCreditCardBalance = (2 << 16),   // 上期未繳餘額 + 利息
} TransactionProperty;

typedef enum {
    TransactionInstallmentPeriodMonthly = 1,
    TransactionInstallmentPeriodQuarterly,
    TransactionInstallmentPeriodSemiannual,
    TransactionInstallmentPeriodAnnual,
    TransactionInstallmentPeriodEnd = TransactionInstallmentPeriodAnnual
} TransactionInstallmentPeriod;

@interface RichTransactionGeneral : NSObject

@property (assign)            int64_t       transId;                 // 交易ID
@property (nonatomic, retain) NSDate *      date;                    // 交易日期
@property (assign)            NSUInteger    categoryCode;            // 交易科目
@property (assign)            NSInteger     accountFrom;             // 付款帳戶/轉出帳戶
@property (assign)            NSInteger     accountTo;               // 收入帳戶/轉入帳戶
@property (assign)            NSInteger     creditCardBillId;        // 信用卡帳單ID
@property (assign)            NSUInteger    installmentPaymentTimes; // 分期總期數
@property (assign)            double        installmentDownPayment;  // 分期頭期款
@property (assign)            double        installmentRate;         // 分期年利率
@property (assign)            NSUInteger    installmentPeriod;       // 分期週期 (月/年)
@property (assign)            NSUInteger    installmentMade;         // 分期付款次數
@property (assign)            int64_t       installmentTransId;      // 分期交易ID
@property (assign)            double        commission;              // 手續費
@property (assign)            double        amount;                  // 交易金額
@property (assign)            NSUInteger    property;                // 交易屬性
@property (assign)            NSUInteger    numberOfReceipts;        // 發票張數
@property (nonatomic, retain) NSString *    receiptNo;               // 發票號碼
@property (nonatomic, retain) NSString *    comment;                 // 交易備註

@end

#pragma mark - Rich Credit Card Info

#define CREDIT_CARD_BILL_ID_NONE    0

@interface RichCreditCardBill : NSObject

@property (assign)            NSInteger         billId;              // 帳單ID
@property (assign)            NSUInteger        accountId;           // 信用卡帳戶ID
@property (nonatomic, retain) NSDate *          closingDate;         // 結帳日期
@property (nonatomic, retain) NSDate *          dueDate;             // 繳款截止日
@property (nonatomic, retain) NSMutableArray *  transactions;        // 關聯交易帳目
@property (nonatomic, retain) NSMutableArray *  payments;            // 本期已繳關聯帳目
@property (assign, readonly)  double            newBalance;          // 本期應繳金額
@property (assign, readonly)  double            payment;             // 本期已繳金額

@end

#pragma mark - Rich Stock Transaction

typedef enum {
    StockTransactionTypeSpotBuy = 0,   // 現貨買進
    StockTransactionTypeSpotSell,      // 現貨賣出
    StockTransactionTypeCashDividend,  // 現金股利
    StockTransactionTypeShareDividend, // 股票股利
    StockTransactionTypeFinanceBuy,    // 融資買進
    StockTransactionTypeFinanceSell,   // 融資賣出
    StockTransactionTypeBearishBuy,    // 融券買進
    StockTransactionTypeBearishSell,   // 融券賣出
    StockTransactionTypeEnd
} StockTransactionType;

@interface RichTransactionStock : NSObject

@property (assign)            int64_t              transId;            // 交易ID
@property (nonatomic, retain) NSDate *             date;               // 成交日期
@property (nonatomic, retain) NSDate *             closingDate;        // 對帳日期
@property (assign)            StockTransactionType type;               // 交易類型
@property (assign)            NSString *           stockCode;          // 股票代碼
@property (assign)            NSInteger            accountStock;       // 證券帳號 (理財帳戶)
@property (assign)            NSInteger            accountSettlement;  // 交割帳號 (Hidden銀行帳戶)
@property (assign)            double               price;              // 股票價格
@property (assign)            NSUInteger           downPaymentPercent; // 融資券成數
@property (assign)            NSUInteger           numberOfShare;      // 成交股數
@property (assign)            double               tradingTax;         // 交易稅
@property (assign)            double               commission;         // 手續費
@property (assign)            double               interest;           // 融資利息; 融券標借券費
@property (assign)            double               amount;             // 淨收付金額
@property (nonatomic, retain) NSString *           comment;            // 交易備註

@end

#pragma mark - Rich Fund Transaction

@interface RichTransactionFund : NSObject

@property (assign)            int64_t   transId;
// TODO: [Fund]

@end

#pragma mark - Rich Core

@interface RichCore : NSObject
{
@public
    SQLiteManager *       sqliteManager;
    
@private
    NSMutableArray * _currTransArray;
    NSString *       _currTransType;
    NSString *       _currTransCondition;
    int64_t          _currTransBegin;
    NSUInteger       _currTransLimit;
    BOOL             _currDescending;
}

@property (assign)            NSUInteger            databaseVersion;
@property (nonatomic, retain) NSMutableDictionary * currencies;
@property (nonatomic, retain) NSMutableDictionary * category;
@property (nonatomic, retain) NSMutableDictionary * creditCardBills;

//
// Database Methods
//

- (int)createTables;

//
// Currency Methods
//

- (int)initCurrency;
- (int64_t)createCurrency:(NSString *)code name:(NSString *)name symbol:(NSString *)symbol position:(NSUInteger)position format:(NSString *)format;
- (NSUInteger)currencyDecimalPosition:(NSString *)code;
- (NSString *)currencyDecimalFormatString:(NSString *)code;
- (NSString *)currencyFormatWithSign:(double)amount code:(NSString *)code;

//
// Account Methods
//

- (RichAccount *)accounts:(NSMutableArray *)accounts findAccountByID:(NSInteger)accountID;
- (RichAccount *)accounts:(NSMutableArray *)accounts findAccountByName:(NSString *)accountName;
- (int)accounts:(NSMutableArray *)accounts loadWithID:(NSInteger)accountID;
- (int)accounts:(NSMutableArray *)accounts loadWithType:(AccountType)type;
- (int)accounts:(NSMutableArray *)accounts loadWithCondition:(NSString *)condition;
- (int64_t)accounts:(NSMutableArray *)accounts create:(RichAccount *)account;
- (int)accounts:(NSMutableArray *)accounts update:(RichAccount *)account;
- (int)accounts:(NSMutableArray *)accounts delete:(NSInteger)accountID;
- (void)accountsCalculateBalance:(NSMutableArray *)accounts;
- (NSString *)accountTypeToString:(AccountType)accountType;
- (NSInteger)accountTypeFromString:(NSString *)accountType;
- (NSString *)accountPropertyToString:(AccountProperty)proterty;
- (NSInteger)accountPropertyFromString:(NSString *)property;

//
// Category Methods
//

- (BOOL)isCategoryNameUnique:(RichCategoryCode)code name:(NSString *)name;
- (NSString *)findCategoryByCode:(RichCategoryCode)code;
- (NSInteger)parentCodeOf:(RichCategoryCode)code atLevel:(NSUInteger)level;
- (NSInteger)levelOfCategoryCode:(RichCategoryCode)code;
- (NSInteger)rootCategoryOf:(RichCategoryCode)code;
- (NSInteger)nextCategoryIdAtLevel:(NSUInteger)level parentCode:(RichCategoryCode)parentCode;
- (NSMutableDictionary *)categoriesAtLevel:(NSUInteger)level parentCode:(RichCategoryCode)parentCode;
- (int)loadCategories;
- (int64_t)createCategory:(RichCategoryCode)categoryCode name:(NSString *)categoryName;
- (int)updateCategory:(RichCategoryCode)categoryCode name:(NSString *)categoryName;
- (int)deleteCategory:(RichCategoryCode)categoryCode;

//
// Transaction Methods
//

- (double)calculateLoanPayment:(double)loan times:(NSUInteger)times annualRate:(double)rate;
- (id *)findTransactionIn:(NSMutableArray *)transactions byID:(int64_t)transID type:(NSString *)type;
- (NSString *)stringFromTransactionProperty:(NSUInteger)property;
- (NSString *)stringFromInstallmentPeriod:(NSUInteger)period;
- (RichTransactionGeneral *)loadGeneralTransaction:(uint64_t)transId;
- (int)loadGeneralTransactions:(NSMutableArray *)transactions category:(RootCategory)rootCategory where:(NSString *)conditions beginAtIndex:(int64_t)begin limit:(NSUInteger)limit descending:(BOOL)descending;
- (int)loadTransactions:(NSMutableArray *)transactions type:(NSString *)type where:(NSString *)conditions beginAtIndex:(int64_t)begin limit:(NSUInteger)limit descending:(BOOL)descending;
- (int64_t)createGeneralTransaction:(RichTransactionGeneral *)transaction;
- (int64_t)createTransaction:(id *)transaction type:(NSString *)type;
- (int)updateGeneralTransaction:(RichTransactionGeneral *)transaction;
- (int)updateTransaction:(id *)transaction type:(NSString *)type;
- (int)deleteTransaction:(int64_t)transactionID type:(NSString *)type;
- (int)deleteTransactionWithCondition:(NSString *)condition type:(NSString *)type;
- (NSUInteger)totalAmountOfTransactions:(NSMutableArray *)transArray;
- (NSUInteger)totalAmountOfPayments:(NSMutableArray *)paymentArray;

//
// Credit Card Bill Methods
//

- (void)creditCardBill:(RichCreditCardBill *)bill loadAssociatedTransactionsToArray:(NSMutableArray *)transArray database:(id *)database;
- (void)creditCardBill:(RichCreditCardBill *)bill loadAssociatedPaymentsToArray:(NSMutableArray *)paymentArray database:(id *)database;
- (void)creditCardBill:(RichCreditCardBill *)bill loadUnassociatedTransactionsToArray:(NSMutableArray *)transArray database:(id *)database;
- (void)creditCardBill:(RichCreditCardBill *)bill loadUnassociatedPaymentsToArray:(NSMutableArray *)paymentArray database:(id *)database;
- (void)creditCardBill:(RichCreditCardBill *)bill disassociateTransactionsFromArray:(NSMutableArray *)transArray database:(id *)database;
- (void)creditCardBill:(RichCreditCardBill *)bill saveTransactionsToDatabase:(id *)database;
- (void)creditCardBill:(RichCreditCardBill *)bill savePaymentsToDatabase:(id *)database;
- (int)loadCreditCardBills;
- (int64_t)createCreditCardBill:(RichCreditCardBill *)bill;
- (int)updateCreditCardBill:(RichCreditCardBill *)bill;
- (int)deleteCreditCardBill:(RichCreditCardBill *)bill;

//
// Common APIs
//

- (NSString *)stringFromDate:(NSDate *)date format:(NSString *)dateFormat;
- (NSDate *)stringToDate:(NSString *)string format:(NSString *)dateFormat;

@end

#endif
